﻿using System;
using System.Collections.Generic;
using CID.Domain.Development;
using CID.Domain.Exceptions;
using CID.Domain.Operations;
using CID.Domain.Users;
using CID.Support;
using NailsFramework.Persistence;

namespace CID.Domain.Audit
{
    public class ReleaseDeploymentLog : Model<ReleaseDeploymentLog>, IReleaseDeploymentLog
    {
        public virtual int Id { get; private set; }
        public virtual DateTime? StartTimestamp { get; private set; }
        public virtual DateTime? EndTimestamp { get; private set; }
        public virtual IUser Responsible { get; private set; }
        public virtual Guid DeploymentUniqueIdentifier { get; private set; }
        public virtual string Details { get; private set; }
        public virtual DeploymentStatus Status { get; private set; }
        public virtual IRelease Release { get; private set; }
        public virtual IEnvironment Environment { get; private set; }
        
        private IList<IVersionDeploymentLog> versions = new List<IVersionDeploymentLog>();
        public virtual IEnumerable<IVersionDeploymentLog> Versions { get { return versions; } }

        protected ReleaseDeploymentLog() : base() 
        {
            DeploymentUniqueIdentifier = Guid.NewGuid();
            Details = String.Empty;
        }

        public ReleaseDeploymentLog(IRelease release, IEnvironment environment, IUser responsible) : this()
        {
            Status = DeploymentStatus.Unknown;
            StartTimestamp = EndTimestamp = null;
            Release = release;
            Environment = environment;
            Responsible = responsible;

            foreach (IVersion version in Release.Versions)
                versions.Add(new VersionDeploymentLog(this, version));
        }

        public virtual void Start()
        {
            if (Status != DeploymentStatus.Unknown) throw new InvalidActionException(String.Format("mark the deployment start when it's in {0} status", Status));
            Status = DeploymentStatus.Started;
            StartTimestamp = ApplicationDateTime.Now;
        }

        public virtual void End(bool successfull)
        {
            if (Status != DeploymentStatus.Started) throw new InvalidActionException(String.Format("mark the deployment end when it's in {0} status", Status));
            Status = successfull ? DeploymentStatus.Succeeded : DeploymentStatus.Failed;
            EndTimestamp = ApplicationDateTime.Now;
        }

        public virtual void AppendDetails(string detailsMessage)
        {
            if (Status != DeploymentStatus.Started) throw new InvalidActionException(String.Format("append message when it's in {0} status", Status));
            Details += detailsMessage + System.Environment.NewLine;
        }
    }
}
